package midas.mw.crt.presence;

import java.net.URI;

import midas.mw.cfg.CfgError;
import midas.mw.cfg.CfgLogging;
import midas.mw.cfg.log.Logger;
import midas.mw.crt.presence.util.MD5ID;
import net.jxta.document.Advertisement;
import net.jxta.document.AdvertisementFactory;
import net.jxta.document.StructuredDocument;
import net.jxta.document.StructuredDocumentFactory;
import net.jxta.document.MimeMediaType;
import net.jxta.document.Element;
import net.jxta.document.Document;
import net.jxta.id.ID;
import net.jxta.id.IDFactory;
import net.jxta.peergroup.PeerGroup;


public class PresenceAdv extends Advertisement 
{    
    
    static final String seperator = "^";
    
    static {
        net.jxta.document.AdvertisementFactory.registerAdvertisementInstance(getAdvertisementType(),new PresenceAdv.Instantiator());
    }
    
    /**
     * Tag to specify the MIDAS node name
     */
    public static final String nameKey= "name";
    
    /**
     * Tag to specify the id that resolved to the JXTA node ID
     */
    public static final String idKey= "ID";
    
    /**
     * Tag to specify the JXTA node ID
     */
    public static final String nodeIDKey= "nodeID"; 
    
    /**
     * Tag to specify the MIDAS node name of proxy
     */
    public static final String proxyNameKey= "proxyName";
    
    /**
     * Tag to specify the MIDAS node type
     */
    public static final String nodeTypeKey= "nodeType";
    
    public static final String indexFields[] = new String[] {idKey, nameKey};
    
    /**
     * Last update to detail presence data
     */
    static final String lastChangedKey = "lastChanged";
    
    /**
     * ID that resolved to the JXTA node ID
     */
    private String id = null; //
    
    /**
     * MIDAS node name
     */
    private String name;
    
    /**
     * JXTA node ID
     */
    private String nodeID;
    
    /**
     * MIDAS node type
     */
    private int nodeType;

    /**
     * MIDAS node name of proxy
     */
    private String proxyName;
    
    /**
     * Long that represents last time a related profile was updated 
     */
    private long lastChanged;
    
    public static final class Instantiator implements AdvertisementFactory.Instantiator 
    {
        /**
         *  {@inheritDoc}
         */
        public String getAdvertisementType() 
        {
        	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "Instantiator.getAdvertisementType()");
        	
            return PresenceAdv.getAdvertisementType();
        }
        
        /**
         *  {@inheritDoc}
         */
        public Advertisement newInstance() 
        {
        	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "Instantiator.newInstance()");
        	
            return new PresenceAdv();
        }
        
        /**
         *  {@inheritDoc}
         */
        public Advertisement newInstance(Element element) 
        {
        	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "Instantiator.newInstance(Element)");
        	
            PresenceAdv adv = new PresenceAdv();
            
            Element elem = (Element) element.getChildren(nameKey).nextElement();
            if (elem !=null && elem.getValue() != null)
                adv.setPresenceName(elem.getValue().toString());
            
            elem = (Element) element.getChildren(idKey).nextElement();
            if (elem !=null && elem.getValue() != null)
                adv.setID(elem.getValue().toString());
                   
            elem = (Element) element.getChildren(nodeIDKey).nextElement();
            if (elem !=null && elem.getValue() != null)
                adv.setPesenceNodeID( elem.getValue().toString().intern());
            
            elem = (Element) element.getChildren( nodeTypeKey ).nextElement();
            if (elem !=null && elem.getValue() != null){
                adv.setNodeType( Integer.parseInt(elem.getValue().toString().intern())  );
            }
            
            elem = (Element) element.getChildren( proxyNameKey ).nextElement();
            if (elem !=null && elem.getValue() != null){
                adv.setProxyName( elem.getValue().toString().intern()  );
            }

            elem = (Element) element.getChildren(lastChangedKey).nextElement();
            if (elem !=null && elem.getValue() != null&& elem.getValue() !="")
            {
                try{
                    adv.setLastChanged( Long.parseLong(elem.getValue().toString()));
                }catch(NumberFormatException nfe){
                	CfgError.errorReporting(CfgError.ERR_OPER, Logger.COMPONENT_CRT, CfgError.SEV_WARNING, "Instantiator.newInstance(Element). " +                 			
                    		"Failed to parse long = '" + elem.getValue().toString()+"'", null);
                    adv.setLastChanged(0);
                }
            }
            return adv;
        }
        
    }
       
    /** Creates a new instance of PresenceAdv */
    public PresenceAdv() 
    {    	
        super();
        
        CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv()");
    }
    
    /**
     * Sets the MIDAS node name
     * @param name MIDAS node name
     */
    public void setPresenceName( String name ) 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.setPresenceName(" + name + ")");
    	
        this.name = name.intern();
    }
    
    /**
     * Gets the MIDAS node name
     * @return MIDAS node name
     */
    public String getPresenceName() 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.getPresenceName()");
    	
        return name;
    }
    
    /**
     * Advertisement type
     */
    
    public static String getAdvertisementType() 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.getAdvertisementType()");
    	
        return "jxta:presence101";
    }
    
    public final String getBaseAdvType() 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.getBaseAdvType()");
    	
        return getAdvertisementType();
    }
    
    /**
     * {@inheritDoc}
     **/
    public Document getDocument(MimeMediaType mimeMediaType) 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.getDocument(MimeMediaType)");
    	
        StructuredDocument doc = StructuredDocumentFactory.newStructuredDocument( mimeMediaType, getAdvertisementType() );
        
        Element elem = doc.createElement( nodeIDKey, nodeID );
        doc.appendChild( elem );
        
        elem = doc.createElement( idKey, id );
        doc.appendChild( elem );
        
        elem = doc.createElement( nameKey, name );
        doc.appendChild( elem );
       
        elem = doc.createElement( nodeTypeKey, Integer.toString(nodeType) );
        doc.appendChild( elem );
        
        elem = doc.createElement( proxyNameKey, proxyName );
        doc.appendChild( elem );
            
        elem = doc.createElement( lastChangedKey, Long.toString(lastChanged) );
        doc.appendChild( elem );
        
        return doc;
    }
    
    public static String makeID(PeerGroup peerGroup, String nodeID)
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.makeID(PeerGroup, " + nodeID + ")");
    	
        ID id = (net.jxta.id.ID)MD5ID.createPipeID(peerGroup.getPeerGroupID(),nodeID,getAdvertisementType() );
        return id.toString();    
    }
    
    public ID getID() 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.getID()");
    	
        try{
            if (id == null){
                //LOG.error("error because ID is null", new RuntimeException());
                return null;
            }
            return (ID) IDFactory.fromURI(new URI(id));
        }catch(Exception e){
        	CfgError.errorReporting(CfgError.ERR_OPER, Logger.COMPONENT_CRT, CfgError.SEV_WARNING, "Instantiator.newInstance(Element). " +                 			
            		"Error converting nodeID = '" + id + "'", null);            
            return null;
        }
    }
    public void setID(String id)
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.setID(" + id + ")");
    	
        this.id = id;
    }    
    
    public String[] getIndexFields() 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.getIndexFields()");
    	
        return indexFields;
    }
    
    /**
     * Gets the JXTA node ID
     * @return JXTA node ID
     */
    public String getPresenceNodeID() 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.getPresenceNodeID()");
    	
        return nodeID;
    }
    
    /**
     * Sets the JXTA node ID
     * @param nodeID JXTA node ID
     */
    public void setPesenceNodeID(String nodeID) 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.setPesenceNodeID(" + nodeID + ")");
    	
        this.nodeID = nodeID.intern();
    }

    /**
     * Gets the MIDAS node type
     * @return MIDAS node type
     */
    public int getNodeType() 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.getNodeType()");
    	
        return nodeType;
    }
    
    /**
     * Sets the MIDAS node type
     * @param nodeType MIDAS node type
     */
    public void setNodeType(int nodeType) 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.setNodeType(" + nodeType + ")");
    	
        this.nodeType = nodeType;
    }
    
    /**
     * Gets the MIDAS node name of the proxy
     * @return JXTA node ID
     */
    public String getProxyName() 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.getProxyName()");
    	
        return proxyName;
    }
    
    /**
     * Sets the MIDAS node name of the proxy
     * @param proxyName MIDAS node name of the proxy
     */
    public void setProxyName(String proxyName) 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.setProxyName(" + proxyName + ")");
    	
        this.proxyName = proxyName;
    }
    
    /**
     * Gets the last update of presence data
     * @return Long that represents last time a related profile was updated
     */   
    public long getLastChanged() 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.getLastChanged()");
    	
        return lastChanged;
    }
    
    /**
     * Sets the last update of presence data
     * @param lastChanged Long that represents last time a related profile was updated
     */ 
    public void setLastChanged(long lastChanged) 
    {
    	CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "PresenceAdv.setLastChanged(" + lastChanged + ")");
    	
        this.lastChanged = lastChanged;
    }         
}